﻿using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MKAdminCore.ToolKit.RedisHelper
{

    /// <summary>
    /// Redis list的实现为一个双向链表，即可以支持反向查找和遍历，更方便操作，不过带来了部分额外的内存开销，
    /// Redis内部的很多实现，包括发送缓冲队列等也都是用的这个数据结构。  
    /// 一般是左进右出或者右进左出 
    /// </summary>
    public class RedisListHelper
    {
        #region 构造函数

        /// <summary>
        /// 初始化Redis的List数据结构操作
        /// </summary>
        /// <param name="dbNum">操作的数据库索引0-64(需要在conf文件中配置)</param>
        static RedisListHelper()
        {
            RedisManager.CreateConn();
        }
        #endregion

        #region 同步方法
        /// <summary>
        /// 从左侧(集合第一个)向list中添加一个值，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long LeftPush<T>(string key, T value)
        {
            try
            {
                string jValue = RedisManager.ConvertJson(value);
                return RedisManager.redis.ListLeftPush(key, jValue);
            }
            catch (Exception ex)
            {
                Console.WriteLine("redisList LeftPush异常:" + ex.ToString());
                return 0;
            }
        }

        /// <summary>
        /// 从左侧(集合第一个)向list中添加多个值，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long LeftPush<T>(string key, List<T> value)
        {
            RedisValue[] valueList = RedisManager.ConvertRedisValue(value.ToArray());
            return RedisManager.redis.ListLeftPush(key, valueList);
        }

        /// <summary>
        /// 从右侧(集合最后)向list中添加一个值，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long RightPush<T>(string key, T value)
        {
            string jValue = RedisManager.ConvertJson(value);
            return RedisManager.redis.ListRightPush(key, jValue);
        }

        /// <summary>
        /// 从右侧(集合最后)向list中添加多个值，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long RightPush<T>(string key, List<T> value)
        {
            RedisValue[] valueList = RedisManager.ConvertRedisValue(value.ToArray());
            return RedisManager.redis.ListRightPush(key, valueList);
        }

        /// <summary>
        /// 从左侧向list中取出一个值并从list中删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T LeftPop<T>(string key)
        {
            var rValue = RedisManager.redis.ListLeftPop(key);
            return RedisManager.ConvertObj<T>(rValue);
        }

        /// <summary>
        /// 从右侧向list中取出一个值并从list中删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T RightPop<T>(string key)
        {
            var rValue = RedisManager.redis.ListRightPop(key);
            return RedisManager.ConvertObj<T>(rValue);
        }

        /// <summary>
        /// 从key的List中右侧取出一个值，并从左侧添加到destination集合中，且返回该数据对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">要取出数据的List名称</param>
        /// <param name="destination">要添加到的List名称</param>
        /// <returns></returns>
        public static T RightPopLeftPush<T>(string key, string destination)
        {
            var rValue = RedisManager.redis.ListRightPopLeftPush(key, destination);
            return RedisManager.ConvertObj<T>(rValue);
        }

        /// <summary>
        /// 在key的List指定值pivot之后插入value，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pivot">索引值</param>
        /// <param name="value">要插入的值</param>
        /// <returns></returns>
        public static long InsertAfter<T>(string key, T pivot, T value)
        {
            string pValue = RedisManager.ConvertJson(pivot);
            string jValue = RedisManager.ConvertJson(value);
            return RedisManager.redis.ListInsertAfter(key, pValue, jValue);
        }

        /// <summary>
        /// 在key的List指定值pivot之前插入value，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pivot">索引值</param>
        /// <param name="value">要插入的值</param>
        /// <returns></returns>
        public static long InsertBefore<T>(string key, T pivot, T value)
        {
            string pValue = RedisManager.ConvertJson(pivot);
            string jValue = RedisManager.ConvertJson(value);
            return RedisManager.redis.ListInsertBefore(key, pValue, jValue);
        }

        /// <summary>
        /// 从key的list中取出数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">开始位置,从零开始</param>
        /// <param name="stop">结束位置(-1:最后一个元素,-2:倒数第二个元素,依此类推)</param>
        /// <returns></returns>
        public static List<T> Range<T>(string key, long start = 0, long stop = -1)
        {
            var rValue = RedisManager.redis.ListRange(key, start, stop);
            return RedisManager.ConvetList<T>(rValue);
        }

        /// <summary>
        /// 从key的List获取指定索引的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static T GetByIndex<T>(string key, long index)
        {
            var rValue = RedisManager.redis.ListGetByIndex(key, index);
            return RedisManager.ConvertObj<T>(rValue);
        }

        /// <summary>
        /// 获取key的list中数据个数
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static long Length(string key)
        {
            try
            {
                return RedisManager.redis.ListLength(key);
            }
            catch (Exception ex)
            {
                Console.WriteLine("异常:" + ex.ToString());
                return 0;
            }

        }

        /// <summary>
        /// 从key的List中移除指定的值，返回删除个数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long Remove<T>(string key, T value)
        {
            string jValue = RedisManager.ConvertJson(value);
            return RedisManager.redis.ListRemove(key, jValue);
        }
        #endregion

        #region 异步方法
        /// <summary>
        /// 从左侧向list中添加一个值，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static async Task<long> LeftPushAsync<T>(string key, T value)
        {
            string jValue = RedisManager.ConvertJson(value);
            return await RedisManager.redis.ListLeftPushAsync(key, jValue);
        }

        /// <summary>
        /// 从左侧向list中添加多个值，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static async Task<long> LeftPushAsync<T>(string key, List<T> value)
        {
            RedisValue[] valueList = RedisManager.ConvertRedisValue(value.ToArray());
            return await RedisManager.redis.ListLeftPushAsync(key, valueList);
        }

        /// <summary>
        /// 从右侧向list中添加一个值，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static async Task<long> RightPushAsync<T>(string key, T value)
        {
            string jValue = RedisManager.ConvertJson(value);
            return await RedisManager.redis.ListRightPushAsync(key, jValue);
        }

        /// <summary>
        /// 从右侧向list中添加多个值，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static async Task<long> RightPushAsync<T>(string key, List<T> value)
        {
            RedisValue[] valueList = RedisManager.ConvertRedisValue(value.ToArray());
            return await RedisManager.redis.ListRightPushAsync(key, valueList);
        }

        /// <summary>
        /// 从左侧向list中取出一个值并从list中删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<T> LeftPopAsync<T>(string key)
        {
            var rValue = await RedisManager.redis.ListLeftPopAsync(key);
            return RedisManager.ConvertObj<T>(rValue);
        }

        /// <summary>
        /// 从右侧向list中取出一个值并从list中删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<T> RightPopAsync<T>(string key)
        {
            var rValue = await RedisManager.redis.ListRightPopAsync(key);
            return RedisManager.ConvertObj<T>(rValue);
        }

        /// <summary>
        /// 从key的List中右侧取出一个值，并从左侧添加到destination集合中，且返回该数据对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">要取出数据的List名称</param>
        /// <param name="destination">要添加到的List名称</param>
        /// <returns></returns>
        public static async Task<T> RightPopLeftPushAsync<T>(string key, string destination)
        {
            var rValue = await RedisManager.redis.ListRightPopLeftPushAsync(key, destination);
            return RedisManager.ConvertObj<T>(rValue);
        }

        /// <summary>
        /// 在key的List指定值pivot之后插入value，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pivot">索引值</param>
        /// <param name="value">要插入的值</param>
        /// <returns></returns>
        public static async Task<long> InsertAfterAsync<T>(string key, T pivot, T value)
        {
            string pValue = RedisManager.ConvertJson(pivot);
            string jValue = RedisManager.ConvertJson(value);
            return await RedisManager.redis.ListInsertAfterAsync(key, pValue, jValue);
        }

        /// <summary>
        /// 在key的List指定值pivot之前插入value，返回集合总数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="pivot">索引值</param>
        /// <param name="value">要插入的值</param>
        /// <returns></returns>
        public static async Task<long> InsertBeforeAsync<T>(string key, T pivot, T value)
        {
            string pValue = RedisManager.ConvertJson(pivot);
            string jValue = RedisManager.ConvertJson(value);
            return await RedisManager.redis.ListInsertBeforeAsync(key, pValue, jValue);
        }

        /// <summary>
        /// 从key的list中取出数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start">开始位置,从零开始</param>
        /// <param name="stop">结束位置(-1:最后一个元素,-2:倒数第二个元素,依此类推)</param>
        /// <returns></returns>
        public static async Task<List<T>> RangeAsync<T>(string key, long start = 0, long stop = -1)
        {
            var rValue = await RedisManager.redis.ListRangeAsync(key, start, stop);
            return RedisManager.ConvetList<T>(rValue);
        }

        /// <summary>
        /// 从key的List获取指定索引的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static async Task<T> GetByIndexAsync<T>(string key, long index)
        {
            var rValue = await RedisManager.redis.ListGetByIndexAsync(key, index);
            return RedisManager.ConvertObj<T>(rValue);
        }

        /// <summary>
        /// 获取key的list中数据个数
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<long> LengthAsync(string key)
        {
            return await RedisManager.redis.ListLengthAsync(key);
        }

        /// <summary>
        /// 从key的List中移除指定的值，返回删除个数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static async Task<long> RemoveAsync<T>(string key, T value)
        {
            string jValue = RedisManager.ConvertJson(value);
            return await RedisManager.redis.ListRemoveAsync(key, jValue);
        }
        #endregion
    }
}
